﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using ICSharpCode.NRefactory.Visitors;
using ICSharpCode.NRefactory;
using Gendarme.Framework;


namespace Commander.Core.Refactorings.Modifiers {

	public interface ICodeModifier {
		string ApplyModification();
		XElement CommanderExtra { get; set; }
	}

	public class ModifierInfo {
		public XElement CommanderExtra { get; set; }
		public FileType Type { get; set; }
		public string FilePath { get; set; }
	}

	public enum FileType { Undefined = 0, CSharp = 1, Java = 2 }



	//can traverse the AST
	public abstract class NetWalkerCodeModifier : AbstractAstVisitor, ICodeModifier {

		public XElement CommanderExtra { get; set; }
		protected IParser m_parser;

		public NetWalkerCodeModifier(XElement commanderExtra, IParser parser) {
			m_parser = parser;
			CommanderExtra = commanderExtra;
		}

		public NetWalkerCodeModifier() {

		}

		public abstract string ApplyModification();
		public static int Differantial = 0;

		private static int genId = -1;
		protected string GenId {
			get {
				genId++;
				return "CommanderGen_" + genId;
			}
		}

		public delegate string SpeculativeGeneralityExtraInfoRequired(string variantClass);
		public static event SpeculativeGeneralityExtraInfoRequired OnSpeculativeGenExtraInforRequired;

		public static NetWalkerCodeModifier CreateModifier(XElement commanderExtra, IParser parser, IRule rule) {
			if (rule.Name.Equals("AvoidCodeDuplicatedInSameClassRule")) {
				return new SameClassDuplicationModifier(commanderExtra, parser);
			}
			else if (rule.Name.Equals("AvoidSpeculativeGeneralityRule") && commanderExtra != null) {

				var modif = new SpeculativeGeneralityModifer(commanderExtra, parser);
				string variantContent = OnSpeculativeGenExtraInforRequired(modif.VariantName);
				modif.VariantParser = ParserFactory.CreateParser(SupportedLanguage.CSharp, new System.IO.StringReader(variantContent));
				modif.VariantParser.Parse();
				return modif;
			}
			else if (rule.Name.Equals("AvoidMessageChainsRule")) {
				return new NetLongMessageChainModifier(commanderExtra, null);
			}
			else {
				throw new ArgumentException(String.Format("Rule {0} does not have a Code Modifier at the moment", rule.Name));
			}
		}
	}

	public class CodeModifiersFactory {
		public delegate string SpeculativeGeneralityExtraInfoRequired(string variantClass);
		public static event SpeculativeGeneralityExtraInfoRequired OnSpeculativeGenExtraInforRequired;

		public static ICodeModifier CreateModifier(ModifierInfo info) {
			return null;
		}

		public static ICodeModifier CreateModifier(XElement commanderExtra, IParser parser, IRule rule) {
			if (rule.Name.Equals("AvoidCodeDuplicatedInSameClassRule")) {
				return new SameClassDuplicationModifier(commanderExtra, parser);
			}
			else if (rule.Name.Equals("AvoidSpeculativeGeneralityRule") && commanderExtra != null) {

				var modif = new SpeculativeGeneralityModifer(commanderExtra, parser);
				string variantContent = OnSpeculativeGenExtraInforRequired(modif.VariantName);
				modif.VariantParser = ParserFactory.CreateParser(SupportedLanguage.CSharp, new System.IO.StringReader(variantContent));
				modif.VariantParser.Parse();
				return modif;
			}
			else if (rule.Name.Equals("AvoidMessageChainsRule")) {
				return new NetLongMessageChainModifier(commanderExtra, null);
			}
			else {
				throw new ArgumentException(String.Format("Rule {0} does not have a Code Modifier at the moment", rule.Name));
			}
		}
	}

}
